package jasmine.orm.db.adapter;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import jasmine.orm.code.DbContext;
import jasmine.orm.query.Query;

public class FindListByIdsDbOperationAdapter<T> extends AbstractDbOperationAdapter<T> {

	private Object[] ids;
	
	public  FindListByIdsDbOperationAdapter(DbContext dbContext, Query<T> query,Object[] ids) {
		super(dbContext, query);
		this.ids = ids;
		if(tableMapping.isCache()) {
			this.query.cache(tableMapping.getCacheTime());
		}
	}
	
	private List<T> executeDbQuery(Object[] ids){
		this.query.where().idIn(ids);
		return query(this.query);
	}
	
	protected  List<T> query(Query<T> query){
		String sql = query.getQueryBuilder().buildSelectSQL();
		if(log.isInfoEnabled() && context.isShowSql()) {
			log.info("==> execute [sql={},params={}]", sql, query.getParams());
		}
		Object[] params = query.getParams().toArray();
		return dbOperation.queryBeanList(query.getTableMapping().getTableClass(), sql, params);
	}
	

	@Override
	public Object cacheAdapter() {

		//keys
		Set<String> keys = Stream.of(ids)
				.distinct()
				.map(key->query.getCacheKey(key.toString()))
				.collect(Collectors.toSet());
		//从缓存中获取
		List<T> list = cacheOperation.list(tableMapping.getTableClass(),keys);
		
		Set<Object> cacheIds = list.stream().map(x->tableMapping.getIdValue(x)).distinct().collect(Collectors.toSet());
		//没有被缓存的key
		List<Object> noCacheIds = Stream.of(ids).filter(x->!cacheIds.contains(x)).collect(Collectors.toList());
		//从数据库中查询		
		if(noCacheIds.isEmpty() ) {
			return list;
		}
		List<T> results = executeDbQuery(noCacheIds.toArray());
		if(results.isEmpty()) {
			return list;
		}
		list.addAll(results);
		Map<String, Object> cacheMap = results.stream().collect(Collectors.toMap(x->query.getCacheKey(tableMapping.getIdValue(x).toString()), v->v));
		//批量写入缓存
		cacheOperation.put(cacheMap, tableMapping.getCacheTime());
		return list;
	}

	@Override
	public Object dbAdapter() {
		return executeDbQuery(ids);
	}


}
